using Commons.Models.OperationsContext;
using Commons.Utils;
using System;
using System.Collections.Generic;

namespace Commons.Services.Functions
{
	public class CalendarVariableEvaluator : IVariableEvaluator
	{
		protected const string Prefix = "C:";

		protected delegate int Calculate(DateTime dateTime);

		protected readonly Dictionary<string, Calculate> calculators = new Dictionary<string, Calculate>
		{
			{ "DAY_OF_WEEK", DayOfWeek },
			{ "DAY_OF_MONTH", DayOfMonth },
			{ "DAY_OF_YEAR", DayOfYear },
			{ "HOUR_OF_WEEK", HourOfWeek },
			{ "HOUR_OF_MONTH", HourOfMonth },
			{ "HOUR_OF_YEAR", HourOfYear },
			{ "MINUTE_OF_WEEK", MinuteOfWeek },
			{ "MINUTE_OF_MONTH", MinuteOfMonth },
			{ "MINUTE_OF_YEAR", MinuteOfYear }
		};

		protected static int DayOfWeek(DateTime dateTime)
		{
			return (int) dateTime.DayOfWeek;
		}

		protected static int DayOfMonth(DateTime dateTime)
		{
			return dateTime.Day;
		}

		protected static int DayOfYear(DateTime dateTime)
		{
			return dateTime.DayOfYear;
		}

		protected static int HourOfWeek(DateTime dateTime)
		{
			return (int) dateTime.DayOfWeek * 24 + dateTime.Hour;
		}

		protected static int HourOfMonth(DateTime dateTime)
		{
			return (dateTime.Day - 1) * 24 + dateTime.Hour;
		}

		protected static int HourOfYear(DateTime dateTime)
		{
			return (dateTime.DayOfYear - 1) * 24 + dateTime.Hour;
		}

		protected static int MinuteOfWeek(DateTime dateTime)
		{
			return ((int) dateTime.DayOfWeek * 24 + dateTime.Hour) * 60 + dateTime.Minute;
		}

		protected static int MinuteOfMonth(DateTime dateTime)
		{
			return ((dateTime.Day - 1) * 24 + dateTime.Hour) * 60 + dateTime.Minute;
		}

		protected static int MinuteOfYear(DateTime dateTime)
		{
			return ((dateTime.DayOfYear - 1) * 24 + dateTime.Hour) * 60 + dateTime.Minute;
		}

		public double? Eval(string variable, IOperationContext context)
		{
			if (variable.StartsWith(Prefix))
			{
				Calculate calculate;
				if (calculators.TryGetValue(variable.Substring(Prefix.Length), out calculate))
				{
					return calculate(DateTimeHelper.Current());
				}
			}

			return null;
		}
	}
}

